package com.triones.ljr.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.config.LJRAuthConfig;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.DeviceType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.DateUtil;
import com.ruoyi.common.utils.HttpUtils;
import com.ruoyi.common.utils.SnCreator;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.redis.RedisUtils;
import com.triones.ljr.entity.dto.WxUserDO;
import com.triones.ljr.service.WeChatService;
import com.triones.ljr.service.WxUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

/**
 * 微信授权
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class WeChatServiceImpl implements WeChatService {

    private final LJRAuthConfig ljrAuthConfig;

    private final WxUserService wxUserService;

    private static final String WX_MINI_ACCESS_TOKEN="{WX}{MINI}{ACCESS_TOKEN}_";

    @Override
    public String wxAuthLogin(String code) {
        JSONObject resJson = this.wxMiniAutoCode(code);
        String openid = Convert.toStr(resJson.get("openid"));
        if (StringUtils.isEmpty(openid) || "null".equals(openid)) {
            throw new RuntimeException(resJson.getStr("errmsg"));
        }
//        String openid = "abc123";
        WxUserDO wxUserDO = wxUserService.getWxUserByOpenid(openid);
        if (wxUserDO == null) {
            wxUserDO = new WxUserDO();
            wxUserDO.setOpenid(openid);
            wxUserDO.setNickName("游客_" + SnCreator.getLJRCode());
            wxUserDO.setSex("3");
            wxUserDO.setStatus("1");
            wxUserDO.setIsDel("0");
            wxUserDO.setTypeMark("0");
            wxUserDO.setCreateTime(DateUtil.getDateTimeString());
            wxUserDO = wxUserService.add(wxUserDO);
        } else {
            if (wxUserDO.getStatus().equals("0")) {
                throw new RuntimeException("用户被禁用！");
            }
        }
        return this.convertMemberLogin(wxUserDO,"xcx");
    }

    @Override
    public String convertMemberLogin(WxUserDO wxUserDO, String deviceType) {
        LoginUser loginUser = new LoginUser();
        loginUser.setUserId(wxUserDO.getId());
        loginUser.setUserType(deviceType);
        LoginHelper.loginByDevice(loginUser, DeviceType.convert(deviceType));
        return StpUtil.getTokenValue();
    }

    @Override
    public String getPhoneNumber(String code, String openid) {
        String content = getUserPhoneNumber(code,openid);
        if (StringUtils.isEmpty(content)){
            throw new ServiceException("获取手机号失败");
        }
        JSONObject json = JSONUtil.parseObj(content);
        log.info("getPhoneNumber = " + json);
        String errcode = json.getStr("errcode");
        if(!"0".equals(errcode)){
            throw new ServiceException("获取手机号失败"+json.getStr("errmsg"));
        }
        JSONObject jsonPhoneInfo = json.get("phone_info",JSONObject.class);
        String phoneNumber =  jsonPhoneInfo.getStr("phoneNumber");
        return phoneNumber;
    }

    /**
     * 登录凭证校验
     */
    private JSONObject wxMiniAutoCode(String code) {
        String appId = ljrAuthConfig.getAppid();
        String appKey = ljrAuthConfig.getSecretKey();
        String url = "https://api.weixin.qq.com/sns/jscode2session?" +
            "appid=" + appId + "&" +
            "secret=" + appKey + "&" +
            "js_code=" + code + "&" +
            "grant_type=authorization_code";
        String resContent = HttpUtils.doGet(url, "UTF-8", 100, 1000);
        if (StringUtils.isEmpty(resContent)){
            throw new RuntimeException("授权失败！");
        }
        JSONObject json = JSONUtil.parseObj(resContent);
        log.info("登录凭证校验 resContent = " + json);
        String errCode = json.getStr("errcode");
        if (ObjectUtil.isEmpty(errCode)){
            return json;
        } else {
            throw new RuntimeException(json.getStr("errmsg"));
        }
    }

    /**
     * 手机号快速验证
     * @param code
     * @return
     */
    private String getUserPhoneNumber(String code,String openid) {
        String accessToken  = RedisUtils.getCacheObject(WX_MINI_ACCESS_TOKEN);
        if (StringUtils.isEmpty(accessToken)){
            accessToken = getAccessToken();
        }
        Map<String, String> parameters = new HashMap<>();
        parameters.put("code",code);
        String url = " https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" +accessToken;
        return HttpUtils.doPostWithJson(url,parameters);
    }

    /**
     * 获取接口调用凭据
     * @return
     */
    private String getAccessToken() {
        String appId = ljrAuthConfig.getAppid();
        String appKey = ljrAuthConfig.getSecretKey();
        String url = " https://api.weixin.qq.com/cgi-bin/token?" +
            "appid=" + appId + "&" +
            "secret=" + appKey + "&" +
            "grant_type=client_credential";
        String content  = HttpUtils.doGet(url, "UTF-8", 100, 1000);
        if (StringUtils.isEmpty(content)){
            throw new ServiceException("获取access_token失败");
        }
        JSONObject json = JSONUtil.parseObj(content);
        log.info("获取接口调用凭据 resContent = " + json);
        String accessToken = json.getStr("access_token");
        if (StringUtils.isEmpty(accessToken)){
            throw new ServiceException("获取access_token失败");
        }
        RedisUtils.setCacheObject(WX_MINI_ACCESS_TOKEN,accessToken, Duration.ofHours(2));
        return accessToken;
    }
}
